#include "bs_app.h"
#include "dev_led.h"

#define LED_LIGHT_ON(e)                   GPIO_BC(e->port) = e->pin
#define LED_LIGHT_OFF(e)                  GPIO_BOP(e->port) = e->pin
#define LED_LIGHT_TOGGLE(e)               GPIO_TG(e->port) = e->pin
#define LED_LIGHT_GET(e)                  (((GPIO_ISTAT(e->port) & (e->pin)) == 0) ? 0:1)
#define led_jif                           (bs_jiffies)

/************ user key begin *************/
extern bs_led_dev_t led_ok;
extern bs_led_dev_t led_ng;
static bs_led_dev_t *leds_t[USER_LEDS_NUMBER] = {&led_ok, &led_ng};
/************ user key end *************/

/*!
    \brief
    \param[in]  none
    \param[out] none
    \retval
*/
int bs_led_register(bs_led_dev_t *led)
{
	return 0;
}


/*!
    \brief      控制 led 点亮、熄灭、闪烁
    \param[in]  none
    \param[out] none
    \retval
*/
int bs_led_ctl(bs_led_dev_t *led, bs_led_state_t cmd, int args)
{
    int status=0;
    switch(cmd)
    {
        case LED_OFF:
            LED_LIGHT_OFF(led);
            led->state = LED_OFF;
            led->st_time = led_jif;
        break;

        case LED_ON:
            LED_LIGHT_ON(led);
            led->state = LED_ON;
            led->st_time = led_jif;
            // 保持时间
            led->interval = args*1000;
        break;

        case LED_SHINE:
            led->state = LED_SHINE;
            led->st_time = led_jif;
            // 保持时间
            led->off_time = led->st_time + args*1000;
            // 闪烁频率 固定300ms
            led->interval = 200;
        break;

        default:
            led->state = LED_IDLE;
        break;
    }
    return status;
}


/*!
    \brief      led模块主程序
    \param[in]  none
    \param[out] none
    \retval
*/
int bs_led_process()
{
    bs_led_dev_t *cur_led = NULL;
    for (int i=0; i<USER_LEDS_NUMBER; i++)
    {
        cur_led = leds_t[i];
        if (cur_led == NULL || cur_led->port == 0) continue;
        switch (cur_led->state) {
            case LED_IDLE:
            case LED_OFF:
                LED_LIGHT_OFF(cur_led);
            break;

            case LED_ON:
                if (led_jif - cur_led->st_time > cur_led->interval) {
                    LED_LIGHT_OFF(cur_led);
                    cur_led->state = LED_IDLE;
                }
            break;

            case LED_SHINE:
                if (led_jif > cur_led->off_time)
                {
                    if (!LED_LIGHT_GET(cur_led)) {
                        LED_LIGHT_OFF(cur_led);
                        cur_led->state = LED_IDLE;
                        break;
                    }
                }
                if (led_jif - cur_led->st_time > cur_led->interval) {
                    LED_LIGHT_TOGGLE(cur_led);
                    cur_led->st_time += cur_led->interval;
                }
            break;
            
            default:
            break;
        }
    }
    return 0;
}
